import { RSAKey } from "../src/rsa/rsa_key.ts";
import { RSA } from "./../mod.ts";

async function benchmark(
  callback: () => Promise<void>,
  time: number,
): Promise<string> {
  const begin = Date.now();
  for (let i = 0; i < time; i++) await callback();
  const duration = Date.now() - begin;
  return (
    "Average time per operation: " +
    (duration / time).toLocaleString(undefined, {
      maximumFractionDigits: 3,
      minimumFractionDigits: 3,
    }) +
    "ms"
  );
}

const RSAWithoutCRT = new RSA(
  new RSAKey({
    n: 18860626341786571281488823024986320858450594409825894653370543036132043241142573896042059032222842653925236802058387508300831766517210547599910735316414515960981281788934868325895562621846910598716519620622800765932541992515497122274302135166053720433521886017494719475895327062855822141735315456613329660043977602681873027347568355824008701177948209784908095092287571982104446342906805480285143028837509076748632094733769028381835899214426100089454654381383340292544225149266603150745375542089871264998183586873913491071542891188124185517417658034185267204900711933432911892469528812455677450346478816563776340692357n,
    e: 65537n,
    d: 675889233296421535959584534071325460876697008626327098961835826056666939623318583538247287416696388446697983317835135300723690022117970081796395234018582764098060974026823771341271141202058228435371968592820841644512299636165137501280011132877728106486853881053264668544941537620562475421678333757690909726581512579603702598150422421865490996288244127528474781858718770957987603681469839575489191876915053252047160475432784849252000744700939988583801783684487872676506769116621572018367654125765915215495461243190782913460732307866572233187464540482209385816659449697777403383908159076257721991916366849321145825505n,
    length: 256,
  }),
);

const RSAWithCRT = new RSA(
  new RSAKey({
    n: 18860626341786571281488823024986320858450594409825894653370543036132043241142573896042059032222842653925236802058387508300831766517210547599910735316414515960981281788934868325895562621846910598716519620622800765932541992515497122274302135166053720433521886017494719475895327062855822141735315456613329660043977602681873027347568355824008701177948209784908095092287571982104446342906805480285143028837509076748632094733769028381835899214426100089454654381383340292544225149266603150745375542089871264998183586873913491071542891188124185517417658034185267204900711933432911892469528812455677450346478816563776340692357n,
    e: 65537n,
    d: 675889233296421535959584534071325460876697008626327098961835826056666939623318583538247287416696388446697983317835135300723690022117970081796395234018582764098060974026823771341271141202058228435371968592820841644512299636165137501280011132877728106486853881053264668544941537620562475421678333757690909726581512579603702598150422421865490996288244127528474781858718770957987603681469839575489191876915053252047160475432784849252000744700939988583801783684487872676506769116621572018367654125765915215495461243190782913460732307866572233187464540482209385816659449697777403383908159076257721991916366849321145825505n,
    p: 144012741627856144888308881334281149724189531338704225677876939563376606824918324031374859287124236226502971065990666108124651521772921507380585859955952240309460362784798071545709251190489395954672667468167440559860853869293126718717957973299492588051948353555478537074738121854154013245465025431728566135973n,
    q: 130964983574331118238688281723343099404807798188351894743739498160286888632365582428908430826736465978859171109808627043780421532713284022169182243601628532694521039146449170161837408903716062502861857136295244082497345869098293182658740508141543051039696970285876309414793236229439985580214897811694398138209n,
    dp:
      101745242578283949839304176626026302615765501625718038014206601700771528284898122271399648057012472126577972233967069321732572665229256933255045035440751035763135842618089328298662278539176953652032498422434484837613519933106647440836151945919299110608989008748123460390840662802554879248234151815614020617785n,
    dq:
      35678301062546466652937128368533312430740473760697540759490440516864704054843143700287335764233224950585953598646920476061700200574682590472688401624478932858201910873563078628399913004363131970125205568021351112332081315087369371243559409682455859030208122243679686715774576798456162206832122091795348953409n,
    qi:
      290194643186456996857651131997752205887237030546449364256620415456526041634563025067464278896891532150660234750257681796597575941847755684751705687345792123358974007946764700824215929859573834912100325612311985272735079519163425874861676228607347917173236103665132111683625679969874392886475792638645717652n,
    length: 256,
  }),
);

const ciper = await RSAWithCRT.encrypt("Hello World");

console.log(
  "With CRT",
  await benchmark(async () => {
    RSAWithCRT.decrypt(ciper);
  }, 1000),
);

console.log(
  "Without CRT",
  await benchmark(async () => {
    RSAWithoutCRT.decrypt(ciper);
  }, 1000),
);
